﻿using Microsoft.AspNet.SignalR.Client;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Common;
using System.Web;
using Newtonsoft.Json.Linq;

namespace SignalrClientTest
{
    /// <summary>
    /// 我希望的是可以把所有的ui和signalr的逻辑分开
    /// </summary>
    public partial class MainForm : Form
    {
        const string testurl2 = "http://localhost:1113/push";
        const string testurl = "http://localhost:1112/push";
        const string apiurl = "http://api.easesales.com/SignalRPush/push";

        HubConnection conn = null;
        IHubProxy msgProxy = null;

        const string machineKey = "1c5ce680de9232883bc249ac567654a266dc94b66aaa6143c8199c828614ce58";
        const string memberId = "1181";
        const string siteId = "19";
        const bool isUseGoogle = true;
        const byte langId = 91;
        const int devicetype = 0; //0表示

        public MainForm()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;

            this.SizeChanged += MainForm_SizeChanged;
            System.Timers.Timer t = new System.Timers.Timer(1000);
            t.Elapsed += T_Elapsed;
            t.AutoReset = true;
            t.Enabled = true;

            txtMemberId.Text = memberId;
            txtMeachineKey.Text = machineKey;

            LinkServer();
        }

        private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //Init();
        }

        private void MainForm_SizeChanged(object sender, EventArgs e)
        {
            this.logText.Width = this.Width;
            this.connLogText.Width = this.Width;
        }

        #region 连接到服务器
        private void LinkServer(bool isReInit = false)
        {
            if (conn == null || isReInit) //如果重新初始化（isReInit=true）的话，就重新实例化Conn
            {
                var para = GetPara();
                string url = para.Item2;

                conn = new HubConnection(url, false);
                conn.TransportConnectTimeout = new TimeSpan(0, 0, 5);
                ServicePointManager.DefaultConnectionLimit = 1;//限制并发数量

                conn.TraceLevel = TraceLevels.All;
                conn.TraceWriter = new DebugTextWriter();
                conn.TraceWriter = new LogTextWriter(connLogText);

                conn.Error += Conn_Error;
                conn.StateChanged += Conn_StateChanged;
                foreach (var item in GetHeaders())
                    conn.Headers.Add(item.Key, item.Value.ToString());

                msgProxy = conn.CreateHubProxy("MsgHub");

                msgProxy.On<string>("Receive", (message) => AddReceiveMsg(message));
                //msgProxy.On<string>("MsgReceive", (message) => MsgReceive(message));
                msgProxy.On<JObject>("MsgReceive", (jObj) => MsgReceive(jObj));
                msgProxy.On("Error", exception => AddReceiveMsg(exception));
            }

            if (conn != null && conn.State == ConnectionState.Disconnected)
            {
                LinkResult();
            }
        }

        private Tuple<string, string> GetPara()
        {
            string url = string.Empty;

            string title = "MainFormdebug";

            if (!Debugger.IsAttached)
            {
                title = "MainFormRelease" + new Random(100).Next();
            }
            title += new Random().Next(100);

            this.Text = title;

            if (rbServer.Checked)
            {
                url = apiurl;
            }
            else if (rbLocal.Checked)
            {
                url = testurl;
            }
            else if (rbText.Checked)
            {
                url = txturl.Text;
                if (!url.StartsWith("http://"))
                {
                    url = "http://" + url;
                }
            }

            return new Tuple<string, string>(title, url);
        }

        private IDictionary<string, object> GetHeaders()
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();

            dict.Add("MachineKey", txtMeachineKey.Text.Trim());//设备机器码
            dict.Add("memberId", txtMemberId.Text.Trim());//用户Id
            dict.Add("siteId", siteId);//网站Id
            dict.Add("isUseGoogle", isUseGoogle);//是否使用google推送服务
            dict.Add("devicetype", "0");//设备类型
            dict.Add("langId", langId); //设备的语言Id

            return dict;
        }
        #endregion


        #region Conn的变化监控
        private void Conn_Error(Exception ex)
        {
            connLogText.AppendText(ex.Message);
        }

        private void Conn_StateChanged(StateChange obj)
        {
            switch (obj.NewState)
            {
                case ConnectionState.Connected:
                    AddLog("已连接");
                    if (!string.IsNullOrEmpty(txtInput.Text))
                    {
                        ChatSend(txtInput.Text);
                        txtInput.Clear();
                    }
                    break;
                case ConnectionState.Connecting:
                    AddLog("努力连接...");
                    break;
                case ConnectionState.Reconnecting:
                    AddLog("努力重连...");
                    break;
                case ConnectionState.Disconnected:
                    AddLog("已断开");
                    break;
            }

        }
        #endregion
        private void ChatSend(string text)
        {
            //msgProxy.Invoke("notify", text);
        }

        #region 写Log
        private void AddLog(string message)
        {
            logText.AppendText(message + Environment.NewLine);
        }

        private void AddReceiveMsg(string message)
        {
            var msg = JsonConvert.DeserializeObject<SignalrMessage>(message);
            AddLog(string.Format("{0}", message));
        }
        private void MsgReceive(string message)
        {
            try
            {
                var msg = JsonConvert.DeserializeObject<SignalrData>(message);
                msgProxy.Invoke("clientNotify", string.Concat(msg.mid, "|", machineKey));
                AddLog(string.Format("{0}", message));
            }
            catch
            {
                AddLog(message);
            }

        }

        private void MsgReceive(JObject jObj)
        {
            string message = string.Empty;
            if (jObj == null)
            {
                message = string.Empty;
            }
            else
            {
                message = JsonConvert.SerializeObject(jObj);
            }

            try
            {
                var msg = JsonConvert.DeserializeObject<SignalrData>(message);
                msgProxy.Invoke("clientNotify", msg.mid, machineKey);
                AddLog(string.Format("{0}", message));
            }
            catch
            {
                AddLog(message);
            }
        }
        #endregion

        #region 连接和断开连接
        /// <summary>
        /// 在Conn.Start()之后立即判断建立结果，并打印错误信息
        /// </summary>
        /// <returns></returns>
        public async Task LinkResult()
        {
            //在Start()之后立即判断建立结果，并打印错误信息
            await conn.Start().ContinueWith((t) =>
            {
                if (t.IsCompleted)
                {
                    if (t.Status == TaskStatus.Faulted)
                    {
                        string str = string.Empty;
                        if (t.Exception?.InnerException != null)
                        {
                            str = t.Exception.InnerException.Message;
                        }
                        else
                        {
                            str = t.Exception.Message;
                        }
                        AddLog(str);
                    }
                }
            });
        }
        private void btnLink_Click(object sender, EventArgs e)
        {
            LinkServer();
        }

        private void btnDisLink_Click(object sender, EventArgs e)
        {
            if (conn != null)
            {
                conn.Stop();
            }
        }
        #endregion

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (conn == null)
                LinkServer();

            var text = txtInput.Text;
            if (string.IsNullOrEmpty(text))
            {
                txtInput.Focus();
                AddLog("请输入数据");
                return;
            }

            ChatSend(text);
            txtInput.Clear();
        }

        #region 日志清除
        private void btnClearLog_Click(object sender, EventArgs e)
        {
            logText.Clear();
        }

        private void btnClearConnLog_Click(object sender, EventArgs e)
        {
            connLogText.Clear();
        }
        #endregion

        private void rb_CheckedChanged(object sender, EventArgs e)
        {
            RadioButton rb = sender as RadioButton;
            if (rb.Checked)
            {
                //重新实例化Connection对象并连接到相应地址
                LinkServer(true);
            }
        }

        private void tbServerLink_TextChanged(object sender, EventArgs e)
        {
            LinkServer(true);
        }

        private void btnReLink_Click(object sender, EventArgs e)
        {
            LinkServer(true);
        }

        private void txturl_TextChanged(object sender, EventArgs e)
        {
            rbText.Checked = true;
        }

        private void btnAdminSend_Click(object sender, EventArgs e)
        {
            //鏈接到服務器之後調用send方法,群發消息給所有鏈接的設備

            string[] devices = (tbDevices.Text ?? "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            msgProxy.Invoke("send", tbAdminSend.Text, devices);
        }

        private void btnPushManager_Click(object sender, EventArgs e)
        {
            //調用接口向pushmanager發送一條消息,及自身的機器碼

            HttpRequest request = new HttpRequest("", txturl.Text, "");

            string url = string.Empty;

            url = string.Format("http://{0}/pushmanager/message/add", request.Url.Authority);
            MessageBox.Show(url);
            try
            {
                PushHelper.SendPush(url, "biglinesys", "123", "456", txtMeachineKey.Text, txtPushManager.Text, "{\"data\":\"" + txtPushManager.Text + "\"}");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
    }
}
